// sequence  queue

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define N 128

typedef struct
{
    int data[N];
    int front; //列队的头   数组的下标
    int rear;  //列队的尾   数组的下标
} sequeue_t;

//空队列的概念：队头等于队尾
//为了区分满队和空对，队列元素个数要比数组元素个数少一个
//满队+1 等于空队
sequeue_t *create_empty_sequeue()
{
    sequeue_t *q = (sequeue_t *)malloc(sizeof(sequeue_t));
    memset(q->data, 0, sizeof(q->data)); //将申请的内存清空（初始化）
    q->front = q->rear = N - 1;          //指向数组的最后一个元素
    return q;
}

int sequeue_is_empty(sequeue_t *q)
{
    return (q->front == q->rear);
}

int sequeue_is_full(sequeue_t *q)
{
    //队尾 +1 == 队头，就是满队
    //任何一个数对N求余，这个数的范围就是 0 —— N-1 ;
    return ((q->rear + 1) % N == q->front); //满队
}

int sequeue_enqueue(sequeue_t *q, int value)
{
    if (sequeue_is_full(q))
    {
        printf("队列已满");
        return -1;
    }
    q->rear = (q->rear + 1) % N;
    q->data[q->rear] = value; //将值写入数组
    return 0;
}

int sequeue_dequeue(sequeue_t *q, int *pvalue)
{
    if (sequeue_is_empty(q))
    {
        printf("队列已空");
        return -1;
    }
    q->front = (q->front + 1) % N;
    *pvalue = q->data[q->front];
    return 0;
}

typedef struct
{
    int data[N]; //数组空间
    int index;   //是数组下标的索引
} seqstack_t;

seqstack_t *create_empty_seqstack()
{
    seqstack_t *s = (seqstack_t *)malloc(sizeof(seqstack_t));
    memset(s->data, 0, sizeof(s->data)); //把数组中内容清为0
    s->index = -1;                       //表示栈里面为空
    return s;
}

//为空为真
int seqstack_is_empty(seqstack_t *s)
{
    return (s->index == -1);
}

int seqstack_is_full(seqstack_t *s)
{
    return (s->index == N - 1);
}

//入栈，压栈
int seqstack_push(seqstack_t *s, int value)
{
    if (seqstack_is_full(s))
    {
        printf("栈已满");
        return -1;
    }

    s->index++;
    s->data[s->index] = value;

    return 0;
}

//出栈,弹栈
int seqstack_pop(seqstack_t *s, int *pvalue)
{
    if (seqstack_is_empty(s))
    {
        printf("栈已空");
        return -1;
    }

    *pvalue = s->data[s->index];
    s->index--;

    return 0;
}

int seqstack_is_size(seqstack_t *s)
{
    return (s->index + 1);
}
//检查队列是否是 1,2,3,4...27
//是这个顺序返回真
//不是返回假
int chack_sequeue(sequeue_t *q)
{
    for (int i = 1; i < 27; i++)
    {
        //正常顺序 1,2,3,4...27
        //
        if (q->data[(q->front + i) % N] > q->data[(q->front + i + 1) % N])
        {
            return 0; //这个顺序不对，返回假
        }
    }
    return 1;
}
int main(int argc, char const *argv[])
{

    sequeue_t *Q = create_empty_sequeue();

    for (int i = 0; i < 27; i++)
    {
        sequeue_enqueue(Q, i + 1);
    }

    seqstack_t *S1 = create_empty_seqstack();  // S1 分钟指示器
    seqstack_t *S5 = create_empty_seqstack();  // S5 5分钟指示器
    seqstack_t *S60 = create_empty_seqstack(); // S60 小时计时器

    int count = 0; //用来记录工作的分数
    int value, t12;
    while (1)
    {
        count++;                    //计算累计时间的
        sequeue_dequeue(Q, &value); //从球队列中取出一个球
        seqstack_push(S1, value);
        /***************************************************************/
        /*分钟指示器工作原理*/
        if (seqstack_is_size(S1) < 5) //如果元素个数小于5.存入S1
        {
            continue;
        }

        seqstack_pop(S1, &value);
        seqstack_push(S5, value);
        //分钟指示器的4个球就会按照按他们被放入的相反顺序加入球队列的队尾
        for (int i = 0; i < 4; i++)
        {
            seqstack_pop(S1, &value); //把球从S1 中取出，放入Q中
            sequeue_enqueue(Q, value);
        }
        /***************************************************************/
        /*5 分钟指示器工作原理*/
        if (seqstack_is_size(S5) < 12) //如果元素个数小于5.存入S1
        {
            continue;
        }

        seqstack_pop(S5, &value);
        seqstack_push(S60, value);
        //分钟指示器的4个球就会按照按他们被放入的相反顺序加入球队列的队尾
        for (int i = 0; i < 11; i++)
        {
            seqstack_pop(S5, &value); //把球从S1 中取出，放入Q中
            sequeue_enqueue(Q, value);
        }
        /***************************************************************/
        /*小时指示器工作原理*/
        if (seqstack_is_size(S60) < 12) //如果元素个数小于5.存入S1
        {
            continue;
        }

        seqstack_pop(S60, &t12); //第12个球拿出来

        //小时指示器的11个球就会按照按他们被放入的相反顺序加入球队列的队尾
        for (int i = 0; i < 11; i++)
        {
            seqstack_pop(S60, &value); //把球从S1 中取出，放入Q中
            sequeue_enqueue(Q, value);
        }

        sequeue_enqueue(Q, t12); //然后第12个球也回到队尾

        /***************************************************************/
        //结束条件
        if (chack_sequeue(Q)) //为真返回，为假继续循环
        {
            break;
        }
        else
        {
            continue;
        }
    }
    // 33120标准答案
    printf("count = %d\n", count);
    return 0;
}
